
package org.soekrat.engine.socraton;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * <p>
 *   Pool of 
 *   {@link Socraton}.
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC)
 */
public final class Socratons2 
{
  private Map<Object, Socraton> m_socratons=new HashMap<Object, Socraton>();
  
  /**
   * <p>
   *   Constructor.
   * </p>
   */
  public Socratons2(){}
  
  /**
   * <p>
   *   Adds.
   * </p>
   * @param socraton Constructor to add.
   * @param ctx      Context.
   * @return Reference to shared
   *         {@link Socraton}, this is in general different from the passed
   *         reference and should replace it.
   */
  public Socraton add(Socraton socraton, String ctx)
  {
    if (socraton==null)
    {
      throw new NullPointerException("socraton");
    }
    if (ctx==null)
    {
      throw new NullPointerException("ctx");
    }
    
    Object id=socraton.getId();
    
    Socraton stored=m_socratons.get(id);
    
    // Same pointer, nothing to do.
    if (socraton==stored) return socraton;
    
    // Have no existing so stores the one received.
    if (stored==null)
    {
      m_socratons.put(id, socraton);
      socraton.setBison(ctx, new Bison(id.toString()));
      return socraton;
    }
    
    return augment(stored, socraton);
  }
  
  private Socraton augment(Socraton stored, Socraton socraton)
  {
    List<String> ctxs=socraton.getContexts();
    for (String ctx : ctxs) stored.addBison(ctx, socraton.getBisons(ctx));
    return stored;
  }
  
  /**
   * <p>
   *   Query.
   * </p>
   * @param q {@link SocratonQuery Query}.
   * @return Found.
   */
  public List<Socraton> get(SocratonQuery q)
  {
    if (q==null)
    {
      throw new NullPointerException("q");
    }
    
    List<Socraton> retVal=new ArrayList<Socraton>();
    
    for (Socraton socraton : m_socratons.values())
    {
      if (q.match(socraton)) retVal.add(socraton);
    }
    
    return retVal;
  }
  
}
